<?php

/**
 * 绑定手机号
 */

namespace app\api\controller;


use app\api\model\User;
use app\common\controller\ApiController;
use app\common\lib\RedisKey;
use app\common\lib\RespCode;
use custom\Redis;
use custom\Token;
use Login\Enter;
use Login\Jwt;
use Login\WangYiSms3;
use Login\WechatAlone;
use Login\WechatApplets;
use think\Exception;
use think\Log;

class Bind extends ApiController {

    protected $notNeedToken = ['createtripartiteaccount'];
    protected $notNeedPhone = ['wxtel'];
    protected $resubmitLock = ['wxtel', 'createtripartiteaccount', 'binwx'];

    const TYPE2 = 2;//微信APP
    const TYPE4 = 4;//苹果
    const TYPE3 = 3;//小程序

    /**
     * 创建三方账户
     * @return false|string
     */
    function createTripartiteAccount() {
        try {
            $params = $this->checkParams('phone,mark,code');
            if ($params === false) {
                return $this->resErr();
            }
            $MARK = 'MARK';
            $post = Enter::decodeMark($params['mark'], $MARK);
            \custom\Log::write($post, 'bind.log');
            if (!$post) {
                throw new Exception('令牌错误,请重新登录获取', RespCode::PARAMS_ERR);
            }
            $type = $post[-1];
            if ($type == 'A') {//ios
                $account = substr($post, 0, strlen($post) - 3);
                $source = self::TYPE4;
                $userinfo['openid'] = '';
                $userinfo['unionid'] = '';
                $userinfo['ios_openid'] = '';
                $userinfo['android_openid'] = '';
                $userinfo['gzh_openid'] = '';
                $userinfo['apple_id'] = $account;
                $code_type = '3';
            }
            if ($type == 'O') {//微信
                $info_arr = explode('_and_', $post);
                $account = $info_arr[0];//openid
                $unionid = substr($info_arr[1], 0, strlen($info_arr[1]) - 3);//unionid
                if ($this->headers['os'] == 1) {//ios
                    $userinfo['ios_openid'] = $account;
                    $userinfo['android_openid'] = '';
                }
                if ($this->headers['os'] == 2) {//android
                    $userinfo['android_openid'] = $account;
                    $userinfo['ios_openid'] = '';
                }
                $source = self::TYPE2;
                $userinfo['openid'] = '';
                $userinfo['unionid'] = $unionid;
                $userinfo['gzh_openid'] = '';
                $userinfo['apple_id'] = '';
                $code_type = '2';
            }
            //验证短信
            $req1 = WangYiSms3::verifySms($params['phone'], $params['code'], RedisKey::VERIFICATION_CODE . $code_type);
            if ($req1) {
                $userinfo['phone'] = $params['phone'];
                $userinfo['nickname'] = '';
                $userinfo['headimgurl'] = '';
                $result = User::createUser($userinfo, $this->headers, $source);
                if ($result) {
                    Enter::delMobileMark($params['mark'], 'MARK');
                }
            }
            return $this->resData('success', $result);
        } catch (Exception $e) {
            return $this->resErr($e->getMessage(), $e->getCode());
        }
    }

    /**
     * 微信小程序用户  绑定手机  + 注册
     * @return false|string
     */
    public function wxtel() {
        try {
            $params = $this->checkParams('encryptedData,iv,code');
            if ($params === false) {
                return $this->resErr();
            }
            $data = WechatApplets::request($params);
            $sessionKey = $data['session_key'];
            if (User::get_openid($data['openid'])) {
                throw new Exception('该账户已存在，请直接登录', RespCode::PARAMS_ERR);
            } else {
                $request = self::decryptDataWXtel($sessionKey, $params['encryptedData'], $params['iv']);
                if (!$request) {
                    \custom\Log::write('电话解析失败', 'wxtel.log');
                    throw new Exception('绑定失败', RespCode::PARAMS_ERR);
                } else {
                    if ($params['user_id'] != $data['openid']) {
                        throw new Exception('绑定失败', RespCode::PARAMS_ERR);
                    } else {
                        $userinfo['phone'] = $request['purePhoneNumber'];
                        $userinfo['openid'] = $data['openid'];
                        $userinfo['unionid'] = $data['unionid'];
                        $userinfo['ios_openid'] = '';
                        $userinfo['android_openid'] = '';
                        $userinfo['gzh_openid'] = '';
                        $userinfo['apple_id'] = '';
                        $userinfo['nickname'] = '';
                        $userinfo['headimgurl'] = '';
                        $daTa = User::createUser($userinfo, $this->headers, self::TYPE3);
                        $token = new Token();
                        $token->delUserToken($this->headers['token'], $token::API_TOKEN);
                        return $this->resData('success', $daTa);
                    }
                }
            }
        } catch (Exception $e) {
            return $this->resErr($e->getMessage(), $e->getCode());
        }
    }

    /**
     * 检验数据的真实性，并且获取解密后的明文.
     * @param $encryptedData string 加密的用户数据
     * @param $iv string 与用户数据一同返回的初始向量
     * @param $data string 解密后的原文
     *
     * @return int 成功0，失败返回对应的错误码
     */
    public static function decryptDataWXtel($sessionKey, $encryptedData, $iv) {
        if (strlen($sessionKey) != 24) {
            return false;
        }
        if (strlen($iv) != 24) {
            return false;
        }

        $iv = url_encode($iv);
        $iv = url_decode($iv);

        $encryptedData = url_encode($encryptedData);
        $encryptedData = url_decode($encryptedData);

        $aesKey = base64_decode($sessionKey);
        $aesIV = base64_decode($iv);
        $aesCipher = base64_decode($encryptedData);

        $result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, OPENSSL_RAW_DATA, $aesIV);
        $dataObj = json_decode($result, true);
        if ($dataObj == NULL) {
            return false;
        }
        return $dataObj;
    }
}
